package com.LachesismStorm.lachesism.core.util;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import com.google.common.cache.CacheBuilder;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.log4j.Log4j2;
import okhttp3.*;
import org.apache.commons.codec.binary.Base64;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.LachesismStorm.lachesism.core.common.enums.CommonEnum.DATE_FORMATTER;

/**
 * * @Author lachesism
 * * @Date 2023-07-19 21:25
 * ▄█          ▄████████  ▄████████    ▄█    █▄       ▄████████    ▄████████  ▄█     ▄████████   ▄▄▄▄███▄▄▄▄
 * ███         ███    ███ ███    ███   ███    ███     ███    ███   ███    ███ ███    ███    ███ ▄██▀▀▀███▀▀▀██▄
 * ███         ███    ███ ███    █▀    ███    ███     ███    █▀    ███    █▀  ███▌   ███    █▀  ███   ███   ███
 * ███         ███    ███ ███         ▄███▄▄▄▄███▄▄  ▄███▄▄▄       ███        ███▌   ███        ███   ███   ███
 * ███       ▀███████████ ███        ▀▀███▀▀▀▀███▀  ▀▀███▀▀▀     ▀███████████ ███▌ ▀███████████ ███   ███   ███
 * ███         ███    ███ ███    █▄    ███    ███     ███    █▄           ███ ███           ███ ███   ███   ███
 * ███▌    ▄   ███    ███ ███    ███   ███    ███     ███    ███    ▄█    ███ ███     ▄█    ███ ███   ███   ███
 * █████▄▄██   ███    █▀  ████████▀    ███    █▀      ██████████  ▄████████▀  █▀    ▄████████▀   ▀█   ███   █▀
 * ▀
 */
@Log4j2
public class LachesismTools {
    private static long startTime;

    public static boolean isEmpty(Object object) {
        if (object == null) {
            return true;
        }
        if (object instanceof List) {
            return ((List) object).size() == 0;
        }
        if (object instanceof String) {
            return ((String) object).trim().equals("");
        }
        return false;
    }

    public static <T> boolean isNotEmpty(Collection<T> collection) {
        return collection != null && !collection.isEmpty();
    }

    public static <K, V> boolean isNotEmpty(Map<K, V> map) {
        return map != null && !map.isEmpty();
    }

    public static <T> boolean isNotEmpty(T[] array) {
        return array != null && array.length != 0;
    }

    public static <T> boolean isNotEmpty(T object) {
        return object != null && !object.toString().isEmpty();
    }

    public static boolean isNotEmpty(String str) {
        return str != null && !str.trim().isEmpty();
    }

    //Integer和String的互相转化
    public static Object Int_Str_Convert(Object obj) {
        if (obj instanceof Integer) {
            return String.valueOf(obj);
        } else if (obj instanceof String) {
            try {
                return Integer.parseInt((String) obj);
            } catch (NumberFormatException e) {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * 安全的字符串比较
     */
    public static boolean equals(String str1, String str2) {
        return str1 == null ? str2 == null : str1.equals(str2);
    }

    /**
     * 读取文本文件
     */
    public static String readFile(String filePath) throws IOException {
        try (BufferedReader reader = new BufferedReader(
                new FileReader(filePath))) {
            StringBuilder content = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                content.append(line).append("\n");
            }
            return content.toString();
        }
    }

    /**
     * 写入文本文件
     */
    public static void writeFile(String content, String filePath)
            throws IOException {
        try (BufferedWriter writer = new BufferedWriter(
                new FileWriter(filePath))) {
            writer.write(content);
        }
    }

    /**
     * 复制文件
     */
    public static void copyFile(String source, String target)
            throws IOException {
        try (InputStream in = new FileInputStream(source);
             OutputStream out = new FileOutputStream(target)) {
            byte[] buffer = new byte[8192];
            int length;
            while ((length = in.read(buffer)) > 0) {
                out.write(buffer, 0, length);
            }
        }
    }

    /**
     * 计时工具
     */
    //第一个调用时开始计时没有返回值
    public static void begin() {
        startTime = System.nanoTime();
    }

    //第二个调用时停止计时并输出两次方法调用之间的时间，返回秒，精确到小数点后4位
    public static double end() {
        long endTime = System.nanoTime();
        double elapsedTime = (endTime - startTime) / 1_000_000_000.0; // 转换为秒
        startTime = 0; // 重置计时器
        return Math.round(elapsedTime * 10000.0) / 10000.0; // 精确到小数点后4位
    }

    /**
     * 输入数字输出中文
     */
    public static String convertChineseAmount(String amount) {
        String[] CN_NUMBERS = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
        String[] CN_UNITS = {"", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟"};
        String CN_INTEGER = "整";
        String CN_POINT = "点";
        StringBuilder sb = new StringBuilder();
        // 分割整数和小数部分
        String[] parts = amount.split("\\.");
        // 转换整数部分
        String integerPart = parts[0];
        int partLength = integerPart.length();
        boolean isLastZero = false;
        for (int i = 0; i < partLength; i++) {
            int digit = Integer.parseInt(String.valueOf(integerPart.charAt(i)));
            int unitPos = (partLength - i - 1) % 4;
            if (digit == 0) {
                isLastZero = true;
                if (unitPos == 0 && (partLength - i - 1) != 0 && !isLastZero) {
                    sb.append(CN_NUMBERS[digit]);
                }
            } else {
                if (isLastZero) {
                    sb.append(CN_NUMBERS[0]);
                }
                isLastZero = false;
                sb.append(CN_NUMBERS[digit]).append(CN_UNITS[unitPos]);
            }
            if (unitPos == 0 && (partLength - i - 1) != 0) {
                int unit = (partLength - i - 1) / 4;
                if (unit == 1) {
                    sb.append(CN_UNITS[4]); // 万
                } else if (unit == 2) {
                    sb.append(CN_UNITS[8]); // 亿
                } else {
                    sb.append(CN_UNITS[unit + 4]);
                }
            }
        }
        // 转换小数部分
        if (parts.length > 1) {
            String decimalPart = parts[1];
            int decimalLength = decimalPart.length();
            if (decimalLength == 1) {
                int digit = Integer.parseInt(decimalPart);
                if (digit != 0) {
                    sb.append(CN_POINT).append(CN_NUMBERS[digit]);
                }
            } else if (decimalLength == 2) {
                int digit1 = Integer.parseInt(String.valueOf(decimalPart.charAt(0)));
                int digit2 = Integer.parseInt(String.valueOf(decimalPart.charAt(1)));
                if (digit1 != 0 && digit2 != 0) {
                    sb.append(CN_POINT).append(CN_NUMBERS[digit1]).append(CN_NUMBERS[digit2]);
                } else if (digit1 != 0) {
                    sb.append(CN_POINT).append(CN_NUMBERS[digit1]);
                } else if (digit2 != 0) {
                    sb.append(CN_POINT).append(CN_NUMBERS[0]).append(CN_NUMBERS[digit2]);
                }
            }
        }
        // 如果小数部分为空，则添加"整"
        if (parts.length == 1) {
            sb.append(CN_INTEGER);
        }
        return sb.toString();
    }


    /**
     * 实现BigDecimal和String的相互转换
     */
    public static Object convert(Object input) {
        if (input instanceof BigDecimal) {
            // 如果输入是BigDecimal，则将其转换为String类型并返回
            BigDecimal decimalNumber = (BigDecimal) input;
            return decimalNumber.toString();
        } else if (input instanceof String) {
            // 如果输入是String，则将其转换为BigDecimal类型并返回
            String stringNumber = (String) input;
            return new BigDecimal(stringNumber);
        } else {
            // 如果输入的类型不是BigDecimal也不是String，则返回null或抛出异常，根据需求进行处理
            return null;
        }
    }

    /**
     * 生成随机乱码
     */
    public static String generateRandomCode(Integer length) {
        String charsA = "0123456789abcdefghijklmnopqrstuvwxyz";
        String charsB = "0123456789";
        String charsC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String charsD = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String charsE = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        Random rand = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int index = rand.nextInt(charsE.length());
            sb.append(charsE.charAt(index));
        }
        return sb.toString();
    }


    public static boolean checkJson(String str) {
        boolean result = false;
        if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(str)) {
            str = str.trim();
            if (str.startsWith("{") && str.endsWith("}")) {
                result = true;
            } else if (str.startsWith("[") && str.endsWith("]")) {
                result = true;
            }
        }
        return result;
    }

    public static void getRequestInfo(HttpServletRequest request) {
        // 获取请求地址
        String requestUrl = request.getRequestURL().toString();

        // 获取完整的请求标头信息
        Enumeration<String> headerNames = request.getHeaderNames();
        Map<String, String> headers = Collections.emptyMap();
        if (headerNames != null) {
            headers = Collections.list(headerNames).stream()
                    .collect(Collectors.toMap(header -> header, request::getHeader));
        }
        // 打印请求信息
        StringBuilder requestInfo = new StringBuilder();
        requestInfo.append("Request URL: ").append(requestUrl).append("\n");
        requestInfo.append("Request Headers:\n");
        headers.forEach((name, value) -> requestInfo.append(name).append(": ").append(value).append("\n"));
        System.out.println("================================================================" + "\n" + requestInfo.toString());
    }

    /**
     * 获取ip
     */
    public static String getRealRequestIp() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (null != ip && ip.contains(",")) {
            ip = ip.substring(0, ip.indexOf(","));
        }
        if (ip == null) {
            ip = "unknown";
        }
        return ip;
    }


    /**
     * 通过ip获取经纬度
     */
    public static String getIpLocation(String ip) {
        try {
            URL url = new URL("http://ip-api.com/json/" + ip);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");
            if (conn.getResponseCode() != 200) {
                throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
            }
            BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
            String output;
            StringBuilder sb = new StringBuilder();
            while ((output = br.readLine()) != null) {
                sb.append(output);
            }
            JSONObject json = new JSONObject(sb.toString());
            String lat = json.getString("lat");
            String lon = json.getString("lon");
            return lat + "," + lon;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 获取IPV6的地址
     */
    public static String getIPv6Address() {
        try {
            URL url = new URL("https://api6.ipify.org/");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");
            if (conn.getResponseCode() != 200) {
                throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
            }
            BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
            StringBuilder sb = new StringBuilder();
            String output;
            while ((output = br.readLine()) != null) {
                sb.append(output);
            }
            conn.disconnect();
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    // 创建一个全局的OkHttpClient实例
    private static final OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)  // 设置连接超时时间
            .readTimeout(10, TimeUnit.SECONDS)     // 设置读取超时时间
            .writeTimeout(10, TimeUnit.SECONDS)    // 设置写入超时时间
            .build();

    /**
     * 发送GET请求
     *
     * @param url 请求的URL
     * @return 返回响应内容
     * @throws IOException 如果发生IO异常
     */
    public static String sendGet(String url) throws IOException {
        // 构建URL，添加请求参数
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
        // 创建Request对象
        Request request = new Request.Builder()
                .url(urlBuilder.build())
                .build();

        // 发起请求并获取响应
        try (Response response = client.newCall(request).execute()) {
            return response.body().string();  // 返回响应内容
        }
    }

    /**
     * 发送POST请求
     *
     * @param url    请求的URL
     * @param params URL请求参数，Map格式
     * @return 返回响应内容
     * @throws IOException 如果发生IO异常
     */
    public static String sendPost(String url, Map<String, String> params) throws IOException {
        // 构建POST请求的Body
        FormBody.Builder formBuilder = new FormBody.Builder();
        if (params != null) {
            params.forEach(formBuilder::add);  // 添加每个表单参数
        }
        // 创建Request对象，设置为POST请求
        Request request = new Request.Builder().url(url).post(formBuilder.build()).build();

        // 发起请求并获取响应
        try (Response response = client.newCall(request).execute()) {
            return response.body().string();  // 返回响应内容
        }
    }

    /**
     * 发送带Body的GET请求
     *
     * @param url    请求的URL
     * @param params URL请求参数，Map格式
     * @param body   请求体的内容
     * @return 返回响应内容
     * @throws IOException 如果发生IO异常
     */
    public static String sendGet(String url, Map<String, String> params, String body) throws IOException {
        // 拼接URL，添加查询参数
        StringBuilder urlBuilder = new StringBuilder(url);
        if (params != null && !params.isEmpty()) {
            urlBuilder.append("?");
            for (Map.Entry<String, String> entry : params.entrySet()) {
                urlBuilder.append(entry.getKey()).append("=")
                        .append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("&");
            }
            urlBuilder.deleteCharAt(urlBuilder.length() - 1); // 删除最后一个多余的&
        }

        // 创建HttpURLConnection连接
        URL realUrl = new URL(urlBuilder.toString());
        HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
        connection.setRequestMethod("GET");  // 设置请求方法为GET
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setDoOutput(true);
        connection.setDoInput(true);

        // 发送请求体
        if (body != null && !body.isEmpty()) {
            connection.getOutputStream().write(body.getBytes(StandardCharsets.UTF_8));
        }
        connection.connect();

        // 读取响应
        BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
        StringBuilder responseBuilder = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            responseBuilder.append(line);
        }
        reader.close();
        connection.disconnect();
        return responseBuilder.toString();  // 返回响应内容
    }

    /**
     * 发送带Body的POST请求
     *
     * @param url    请求的URL
     * @param params URL请求参数，Map格式
     * @param body   请求体的内容
     * @return 返回响应内容
     * @throws IOException 如果发生IO异常
     */
    public static String sendPost(String url, Map<String, String> params, String body) throws IOException {
        // 拼接URL，添加查询参数
        StringBuilder urlBuilder = new StringBuilder(url);
        if (params != null && !params.isEmpty()) {
            urlBuilder.append("?");
            for (Map.Entry<String, String> entry : params.entrySet()) {
                urlBuilder.append(entry.getKey()).append("=")
                        .append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("&");
            }
            urlBuilder.deleteCharAt(urlBuilder.length() - 1); // 删除最后一个多余的&
        }

        // 创建HttpURLConnection连接
        URL realUrl = new URL(urlBuilder.toString());
        HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
        connection.setRequestMethod("POST");  // 设置请求方法为POST
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setDoOutput(true);
        connection.setDoInput(true);

        // 发送请求体
        if (body != null && !body.isEmpty()) {
            connection.getOutputStream().write(body.getBytes(StandardCharsets.UTF_8));
        }
        connection.connect();

        // 读取响应
        BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
        StringBuilder responseBuilder = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            responseBuilder.append(line);
        }
        reader.close();
        connection.disconnect();
        return responseBuilder.toString();  // 返回响应内容
    }


    /**
     * 获取时间格式，传入需要的类型，如"yyyy_MM_dd HH_mm_ss"  yyyy年MM月dd日HH时mm分ss秒  或 E 获取日期
     */
    public static String getTime(String patten) {//获取时间字符串
        Date date = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat(patten);
        String time = formatter.format(date);
        return time;
    }

    /**
     * 获取今天是什么星座
     */
    public static String[] getZodiacSign() {
        Calendar calendar = Calendar.getInstance();
        int month = calendar.get(Calendar.MONTH) + 1; // 获取月份，Calendar.MONTH 从0开始
        int day = calendar.get(Calendar.DAY_OF_MONTH); // 获取日期

        if (month > 12 || day < 1 || day > 31) {
            return null;
        }

        // 使用数组和日期区间简化判断
        String[][] zodiacDates = {
                {"capricornus", "摩羯", "1-20", "2-18"},  // 摩羯：1月20日-2月18日
                {"aquarius", "水瓶", "2-19", "3-20"},  // 水瓶：2月19日-3月20日
                {"pisces", "双鱼", "2-29", "3-20"},  // 双鱼：2月29日-3月20日
                {"aries", "白羊", "3-21", "4-19"},  // 白羊：3月21日-4月19日
                {"taurus", "金牛", "4-20", "5-20"},  // 金牛：4月20日-5月20日
                {"gemini", "双子", "5-21", "6-21"},  // 双子：5月21日-6月21日
                {"cancer", "巨蟹", "6-22", "7-22"},  // 巨蟹：6月22日-7月22日
                {"leo", "狮子", "7-23", "8-22"},  // 狮子：7月23日-8月22日
                {"virgo", "处女", "8-23", "9-22"},  // 处女：8月23日-9月22日
                {"libra", "天秤", "9-23", "10-23"},// 天秤：9月23日-10月23日
                {"scorpio", "天蝎", "10-24", "11-22"},// 天蝎：10月24日-11月22日
                {"sagittarius", "射手", "11-23", "12-21"},// 射手：11月23日-12月21日
                {"capricornus", "摩羯", "12-22", "1-19"}  // 摩羯：12月22日-1月19日
        };

        // 遍历星座和对应日期范围
        for (String[] zodiac : zodiacDates) {
            String startDate = zodiac[2];
            String endDate = zodiac[3];

            int startMonth = Integer.parseInt(startDate.split("-")[0]);
            int startDay = Integer.parseInt(startDate.split("-")[1]);
            int endMonth = Integer.parseInt(endDate.split("-")[0]);
            int endDay = Integer.parseInt(endDate.split("-")[1]);

            // 判断日期是否在范围内
            if ((month == startMonth && day >= startDay) || (month == endMonth && day <= endDay)) {
                return zodiac;
            }
        }

        return null; // 不符合任何星座的情况
    }


    /**
     * 获取时间格式，传入需要的类型，如"yyyy_MM_dd HH_mm_ss"  yyyy年MM月dd日HH时mm分ss秒  或 E 获取日期
     */
    public static String getTomorrowTime(String patten) {//获取时间字符串
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 1);
        SimpleDateFormat formatter = new SimpleDateFormat(patten);
        return formatter.format(calendar.getTime());
    }

    /**
     * 时间戳转时间
     */
    public static String timeStampToDate(Long time) {
        long timestamp = time; // Replace with your timestamp
        // Convert timestamp to LocalDateTime
        LocalDateTime beginDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
        // Format LocalDateTime as a string
        String formattedDateA = beginDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
//        System.out.println("开始时间时间戳：" + timestamp + "    时间为" + formattedDateA);
        return formattedDateA;
    }

    /**
     * 添加千分位，并支持小数点后三位
     */
    public static String thousandsSeparator(String number) {
        BigDecimal bigDecimal = new BigDecimal(number);
        DecimalFormat decimalFormat = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US);
        decimalFormat.setGroupingUsed(true);
        decimalFormat.setMaximumFractionDigits(3);
        return decimalFormat.format(bigDecimal);
    }

    /**
     * 反转字符串
     */
    public static String reverseString(String str) {
        StringBuilder sb = new StringBuilder(str);
        sb.reverse();
        return sb.toString();
    }


    /**
     * 反转数字
     */
    public static int reverseNumber(int number) {
        int reversedNumber = 0;
        while (number != 0) {
            int digit = number % 10;
            reversedNumber = reversedNumber * 10 + digit;
            number /= 10;
        }
        return reversedNumber;
    }

    /**
     * 截取字符串，输入开始字符和结束字符，并输入开始字符长度，获取中间的值
     */
    public static String interceptString(String info, String begin, String end) {
        int startIndex = info.indexOf(begin) + begin.length();
        int endIndex = info.indexOf(end);
        return info.substring(startIndex, endIndex);
    }

    /**
     * String[]数组转Integer[]数组
     */
    public static Integer[] convertStringArrayToIntArray(String[] stringArray) {
        return Arrays.stream(stringArray)
                .map(Integer::parseInt)
                .toArray(Integer[]::new);
    }

    /**
     * Integer[]数组转String[]数组
     */
    public static String[] convertIntArrayToStringArray(Integer[] intArray) {
        return Arrays.stream(intArray)
                .map(String::valueOf)
                .toArray(String[]::new);
    }

    /**
     * String[]数组转IntegerList
     */

    public static List<Integer> convertArrayToIntegerList(String[] array) {
        List<Integer> integerList = new ArrayList<>();
        for (String str : array) {
            integerList.add(Integer.parseInt(str));
        }
        return integerList;
    }


    /**
     * String[]数组转List<>
     */
    public static List<String> convertStringArrayToList(String[] stringArray) {
        return Arrays.asList(stringArray);
    }

    /**
     * Integer[]数组转List<>
     */
    public static List<Integer> convertIntegerArrayToList(Integer[] integerArray) {
        return Arrays.asList(integerArray);
    }

    /**
     * List<>转String[]数组
     */
    public static String[] convertListToStringArray(List<String> stringList) {
        return stringList.toArray(new String[0]);
    }

    /**
     * List<>转Integer[]数组
     */
    public static Integer[] convertListToIntegerArray(List<Integer> integerList) {
        return integerList.toArray(new Integer[0]);
    }


    /**
     * 加密
     */
    public static String encrypt(String content) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
        cipher.init(Cipher.ENCRYPT_MODE, getSecretKey("LachesismStorm24"));
        byte[] result = cipher.doFinal(byteContent);
        return org.apache.commons.codec.binary.Base64.encodeBase64String(result);
    }

    public static String encrypt(String content, String key) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
        cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));
        byte[] result = cipher.doFinal(byteContent);
        return org.apache.commons.codec.binary.Base64.encodeBase64String(result);
    }

    /**
     * 解密
     */
    public static String decrypt(String content) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, getSecretKey("LachesismStorm24"));
        byte[] result = cipher.doFinal(Base64.decodeBase64(content));
        return new String(result, StandardCharsets.UTF_8);
    }

    /**
     * 解密
     */
    public static String decrypt(String content, String key) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
        byte[] result = cipher.doFinal(Base64.decodeBase64(content));
        return new String(result, StandardCharsets.UTF_8);
    }

    /**
     * 生成加密秘钥
     */
    private static Key getSecretKey(final String key) {
        return new SecretKeySpec(key.getBytes(), "AES");
    }


    /**
     * 生成二维码
     */
    public static void QRCode(String content) throws Exception {
        BufferedImage image = createImage(content, null, false);
        File file = new File("/Users/yuno/Pictures/" + content + ".png");
        // 当文件夹不存在时，mkdirs会自动创建多层目录，区别于mkdir．(mkdir如果父目录不存在则会抛出异常)
        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }
        ImageIO.write(image, "PNG", new File("/Users/yuno/Pictures/" + content + ".png"));
    }

    public static BufferedImage createImage(String content, String logoPath, boolean needCompress) throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, 300, 300,
                hints);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        // 插入图片
        return image;
    }

    /**
     * urlDecode
     */
    public static String decodeURL(String url) {
        try {
            String decodedURL = URLDecoder.decode(url, "UTF-8");
            return decodedURL;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * urlEncode
     */
    public static String encodeURL(String url) {
        try {
            String encodedUrl = URLEncoder.encode(url, "UTF-8");
            return encodedUrl;
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 正则表达式
     */
    public static String extractURLParameter(String url) {
        String[] parts = url.split("\\?v[1-3]/");
        if (parts.length > 1) {
            return parts[1].replaceAll("/", "");
        }
        return null;
    }

    /**
     * 获取日期
     */
    public static String[] getDatesInRange(Date beginTime, Date endTime) {
        List<String> datesInRange = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(beginTime);
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMATTER);
        while (calendar.getTime().before(endTime) || calendar.getTime().equals(endTime)) {
            Date currentDate = calendar.getTime();
            String dateString = sdf.format(currentDate); // 将日期转换为字符串形式
            datesInRange.add(dateString);
            calendar.add(Calendar.DATE, 1);
        }
        return datesInRange.toArray(new String[0]);
    }

    /**
     * 获取月份
     */
    public static String[] getMonthsInRange(Date beginTime, Date endTime) {
        List<String> monthsInRange = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(beginTime);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        while (calendar.getTime().before(endTime) || calendar.getTime().equals(endTime)) {
            Date currentDate = calendar.getTime();
            String monthString = sdf.format(currentDate); // Convert date to string format
            monthsInRange.add(monthString);
            calendar.add(Calendar.MONTH, 1); // Increment by month instead of date
        }
        return monthsInRange.toArray(new String[0]);
    }

    /**
     * 阿里云文档地址转路径和名称
     */
    public static String[] getBucketAndFileName(String url) {
        String s = decodeURL(url);
        String[] split = s.split(".oss");
        String[] split1 = split[0].split("//");
        String[] split2 = s.split("com/");
        String fileName = split2[1];
        String bucket = split1[1];
        String[] fileInfo = new String[2];
        fileInfo[0] = bucket;
        fileInfo[1] = fileName;
        return fileInfo;
    }


    /**
     * 获取内容的Md5值
     */
    public static String getMd5(String text) {
        try {
            // 获取 MD5 摘要算法实例
            MessageDigest md = MessageDigest.getInstance("MD5");

            // 计算 MD5 值
            byte[] bytes = md.digest(text.getBytes(StandardCharsets.UTF_8));

            // 将字节数组转换为 32 位长度的十六进制字符串
            return String.format("%032x", new java.math.BigInteger(1, bytes));
        } catch (NoSuchAlgorithmException e) {
            // 如果没有找到 MD5 算法，抛出运行时异常
            throw new RuntimeException("MD5加密失败", e);
        }
    }

    /**
     * 获取文件的Md5值
     */
    public static String calculateMD5(File file) throws IOException, NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        try (InputStream fis = new FileInputStream(file)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                md.update(buffer, 0, bytesRead);
            }
        }
        byte[] hashBytes = md.digest();
        StringBuilder hexString = new StringBuilder();
        for (byte b : hashBytes) {
            hexString.append(String.format("%02x", b));
        }
        return hexString.toString();
    }

    /**
     * 将文件转换为Base64字符串
     */
    public static String fileToBase64(File file) throws IOException {
        byte[] fileBytes = Files.readAllBytes(file.toPath());
        return Base64.encodeBase64String(fileBytes);
    }

    /**
     * SHA256加密
     */
    // SHA256加密
    public static String sha256(String text) {
        try {
            // 获取 SHA-256 摘要算法实例
            MessageDigest md = MessageDigest.getInstance("SHA-256");

            // 计算 SHA-256 值
            byte[] bytes = md.digest(text.getBytes(StandardCharsets.UTF_8));

            // 将字节数组转换为 64 位长度的十六进制字符串
            return String.format("%064x", new java.math.BigInteger(1, bytes));
        } catch (NoSuchAlgorithmException e) {
            // 如果没有找到 SHA-256 算法，抛出运行时异常
            throw new RuntimeException("SHA256加密失败", e);
        }
    }


    /**
     * 生成UUID（带横线）
     */
    public static String generateUUID() {
        return UUID.randomUUID().toString();
    }

    public static String generateOrderSn() {
        String timePart = getTime("yyMMddHHmmSS");
        String randomPart = generateRandomCode(4);
        return timePart + randomPart;
    }


    /**
     * =========================================验证码生成器=====================================
     */

    public static void captchaGenerator() {
        switch (Get1To4Randomly()) {
            case 1:
                captchaGeneratorByAddition();//加法
                break;
            case 2:
                captchaGeneratorBySubtraction();//减法
                break;
            case 3:
                captchaGeneratorByMultiplication();//乘法
                break;
            case 4:
                captchaGeneratorByDivision();//除法
                break;
            case 5:
                captchaGeneratorByCode();
                break;
            default:
                // 处理未知情况的代码
                break;
        }
    }


    private static void captchaGeneratorByCode() {
        int codeLength = 5;
        String code = generateRandomCode(codeLength);
        BufferedImage image = generateCode(code, codeLength);
        try {
            File output = new File("/Users/yuno/Pictures/code/" + code + ".png");
            ImageIO.write(image, "png", output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private static void captchaGeneratorByDivision() {
        Random rand = new Random();
        List<Integer> factorNum = generateFactorNumber(2);
        Integer num2 = factorNum.get(1);
        Integer num1 = num2 * (rand.nextInt(30) + 1);
        String info = num1 + "÷" + num2 + "= ?";
        int codeLength = info.length();
        String code = String.valueOf(num1 / num2);
        BufferedImage image = generateCode(info, codeLength);
        try {
            File output = new File("/Users/yuno/Pictures/code/" + info + code + ".png");
            ImageIO.write(image, "png", output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void captchaGeneratorByMultiplication() {
        List<Integer> factorNum = generateFactorNumber(2);
        Integer num1 = factorNum.get(0);
        Integer num2 = factorNum.get(1);
        String info = num1 + "x" + num2 + "= ?";
        int codeLength = info.length();
        String code = String.valueOf(num1 * num2);
        BufferedImage image = generateCode(info, codeLength);
        try {
            File output = new File("/Users/yuno/Pictures/code/" + info + code + ".png");
            ImageIO.write(image, "png", output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void captchaGeneratorBySubtraction() {
        List<Integer> factorNum = generateFactorNumber(2);
        Integer num1 = factorNum.get(0);
        Integer num2 = factorNum.get(1);
        String info = num1 + "-" + num2 + "= ?";
        int codeLength = info.length();
        String code = String.valueOf(num1 - num2);
        BufferedImage image = generateCode(info, codeLength);
        try {
            File output = new File("/Users/yuno/Pictures/code/" + info + code + ".png");
            ImageIO.write(image, "png", output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private static void captchaGeneratorByAddition() {
        List<Integer> factorNum = generateFactorNumber(2);
        Integer num1 = factorNum.get(0);
        Integer num2 = factorNum.get(1);
        String info = num1 + "+" + num2 + "= ?";
        int codeLength = info.length();
        String code = String.valueOf(num1 + num2);
        BufferedImage image = generateCode(info, codeLength);
        try {
            File output = new File("/Users/yuno/Pictures/code/" + info + code + ".png");
            ImageIO.write(image, "png", output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
        随机获取1/2/3/4
     */
    public static Integer Get1To4Randomly() {
        Random rand = new Random();
        int number = rand.nextInt(5) + 1;
        return number;
    }

    /**
     * 生成随机数排序
     */
    public static List<Integer> generateFactorNumber(Integer count) {
        Random rand = new Random();
        LinkedList<Integer> factorNumber = new LinkedList<>();
        for (int i = 0; i < count; i++) {
            int i1 = rand.nextInt(300) + 1;
            factorNumber.add(i1);
        }
        Collections.sort(factorNumber, Collections.reverseOrder());
        return factorNumber;
    }

    private static BufferedImage generateCode(String info, Integer codeLength) {
        int width = 200;
        int height = 40;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();
        // Set background color
        g.setColor(Color.LIGHT_GRAY);
        g.fillRect(0, 0, width, height);
        // Draw lines
        Random rand = new Random();
        for (int i = 0; i < 5; i++) {
            int x1 = rand.nextInt(width);
            int y1 = rand.nextInt(height);
            int x2 = rand.nextInt(width);
            int y2 = rand.nextInt(height);
            g.setColor(Color.red);
            g.drawLine(x1, y1, x2, y2);
        }
        g.setFont(new Font("Roman", Font.ITALIC, 20));
        for (int i = 0; i < codeLength; i++) {
            int x = 20 * i + 10;
            int y = 25;
            g.setColor(new Color(rand.nextInt(255), rand.nextInt(255), 0));
            g.drawString(info.charAt(i) + "", x, y);
        }
        return image;
    }
    //============================验证码生成器=====================================


    /**
     * 微信xml转map工具类
     */
    public static Map<String, String> xmlToMap(InputStream inputStream) {
        Map<String, String> map = new HashMap<>();
        try {
            SAXReader reader = new SAXReader();
            org.dom4j.Document document = reader.read(inputStream);
            Element root = document.getRootElement();
            List<Element> elementList = root.elements();
            // 遍历所有子节点
            for (Element e : elementList)
                map.put(e.getName(), e.getText());
            // 释放资源
            inputStream.close();
        } catch (IOException | DocumentException e) {
            log.info("xml转化为map出现异常：{}", e.getMessage());
        }
        return map;
    }

    /**
     * 大小转化器 Byte =》 转化到自动类型
     */
    public static String convertFileSize(long sizeInBytes) {
        String[] units = {"Byte", "KB", "MB", "GB", "TB", "PB"};
        double size = sizeInBytes;
        int unitIndex = 0;
        while (size >= 1000 && unitIndex < units.length - 1) {
            size /= 1000;
            unitIndex++;
        }
        return String.format("%.1f %s", size, units[unitIndex]);
    }

    /**
     * Md5生成器
     */
    public static String getMD5(String input) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(input.getBytes());
        byte[] digest = md.digest();
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    /**
     * 时间戳转日期
     */
    public static Date stringToDate(String dateStr) {
        long timestamp = Long.parseLong(dateStr);
        Instant instant = Instant.ofEpochSecond(timestamp);
        Date date = Date.from(instant);
        return date;
    }

    /**
     * 时间戳转日期
     */
    public static String dateToString(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
        String str = sdf.format(date);
        return str;
    }

    public static String downloader(String urlString, String savePath) throws IOException {
        String fileName = LachesismTools.getTime("yyyyMMddHHmmss") + LachesismTools.generateRandomCode(2) + ".jpg";
        // 构造URL
        URL url = new URL(urlString);
        // 打开连接
        URLConnection con = url.openConnection();
        // 设置请求超时为20s
        con.setConnectTimeout(20 * 1000);
        // 文件路径不存在则创建
        File sf = new File(savePath);
        if (!sf.exists()) {
            sf.mkdirs();
        }
        try (InputStream in = con.getInputStream();
             OutputStream out = new FileOutputStream(sf.getPath() + File.separator + fileName)) {
            // 创建缓冲区
            byte[] buff = new byte[1024];
            int n;
            // 开始读取
            while ((n = in.read(buff)) >= 0) {
                out.write(buff, 0, n);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fileName;
    }

    public static boolean isValidPhoneNumber(String phoneNumber) {
        String regex = "^1[3456789]\\d{9}$";
        return Pattern.matches(regex, phoneNumber);
    }

    public static String generateRandomCode() {
        SecureRandom random = new SecureRandom();
        StringBuilder code = new StringBuilder(5);
        for (int i = 0; i < 5; i++) {
            code.append(random.nextInt(10));
        }
        return code.toString();
    }

    public static String convertMapToXml(Map<String, String> map) throws JAXBException {
        // 创建一个TreeMap来保持键的顺序（如果需要）
        TreeMap<String, String> sortedMap = new TreeMap<>(map);
        // 创建JAXB上下文
        JAXBContext context = JAXBContext.newInstance(TreeMap.class);

        // 创建Marshaller对象来执行转换
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); // 设置格式化输出
        // 创建StringWriter来写入XML
        StringWriter writer = new StringWriter();
        // 将TreeMap对象转换为XML
        marshaller.marshal(sortedMap, writer);
        // 返回XML字符串
        return writer.toString();
    }

    /**
     * 查看今天是否是周天
     */
    public static boolean isTodayMonday() {
        // 获取今天的日期
        LocalDate today = LocalDate.now();
        // 获取今天是星期几
        DayOfWeek dayOfWeek = today.getDayOfWeek();
        // 判断是否是周天（SUNDAY）
        return dayOfWeek == DayOfWeek.MONDAY;
    }

    /**
     * 查看今天是否是本月最后一天
     */
    public static boolean isFirstDayOfMonth() {
        // 获取今天的日期
        LocalDate today = LocalDate.now();
        // 判断今天的日期是否是本月的第一天
        return today.getDayOfMonth() == 1;
    }

    /**
     * 查看今天是否是今年最后一天
     */
    public static boolean isFirstDayOfYear() {
        // 获取今天的日期
        LocalDate today = LocalDate.now();
        // 判断今天的月份是否是1月，且日期是否是1号
        return today.getMonthValue() == 1 && today.getDayOfMonth() == 1;
    }

    /**
     * 获取到今天结束的秒
     */
    public static long getSecondsUntilMidnight() {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();

        // 设置目标时间为今天的 23:59:59
        LocalDateTime midnight = now.toLocalDate().atTime(23, 59, 59);

        // 计算从当前时间到午夜的秒数
        return ChronoUnit.SECONDS.between(now, midnight);
    }

    /**
     * 手机号脱敏
     */
    public static String maskPhone(String phone) {
        if (isEmpty(phone)) {
            return phone;
        }
        return phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
    }

    /**
     * 身份证脱敏
     */
    public static String maskIdCard(String idCard) {
        if (isEmpty(idCard)) {
            return idCard;
        }
        return idCard.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1**********$2");
    }

    /**
     * 银行卡脱敏
     */
    public static String maskBankCard(String bankCard) {
        if (isEmpty(bankCard)) {
            return bankCard;
        }
        return bankCard.replaceAll("(\\d{4})\\d+(\\d{4})", "$1****$2");
    }

}


/**
 *
 */